package net.chenlin.dp.modules.business.service.impl;

import lombok.extern.slf4j.Slf4j;
import net.chenlin.dp.common.entity.Page;
import net.chenlin.dp.common.entity.Query;
import net.chenlin.dp.common.entity.R;
import net.chenlin.dp.common.exception.RRException;
import net.chenlin.dp.common.utils.CommonUtils;
import net.chenlin.dp.modules.business.dao.DistrictManageMapper;
import net.chenlin.dp.modules.business.entity.dto.DistrictChildDto;
import net.chenlin.dp.modules.business.entity.dto.DistrictDto;
import net.chenlin.dp.modules.business.entity.po.DistrictPo;
import net.chenlin.dp.modules.business.entity.po.DistrictTreePo;
import net.chenlin.dp.modules.business.entity.vo.districtManage.DistrictManageListVo;
import net.chenlin.dp.modules.business.entity.vo.districtManage.DistrictTreeVo;
import net.chenlin.dp.modules.business.service.DistrictManageService;
import org.apache.commons.collections4.Bag;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.bag.HashBag;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author Yangsm
 * @ClassName: DistrictManageServiceImpl
 * @Description: TODO
 * @date 2023年05月01日 16:44
 */
@Service
@Slf4j
public class DistrictManageServiceImpl implements DistrictManageService {

    @Autowired
    private DistrictManageMapper districtManageMapper;

    @Override
    public Page<DistrictManageListVo> getDistrictList(Map<String, Object> params) {
        Query query = new Query(params);
        Page<DistrictManageListVo> page = new Page<>(query);
        List<DistrictManageListVo> list = districtManageMapper.getDistrictList(page, query);
        list.stream().forEach(vo -> {
            // 获取在线个数
            List<Integer> deviceStatus = districtManageMapper.getDeviceStatus(vo.getDistrictId());
            Bag bag = new HashBag(deviceStatus);
            int count = bag.getCount(0);
            vo.setOnlineNum(count);
            vo.setCurStatus("监测中");
            if (count == 0) {
                // 监测结束（所有设备全部离线）
                vo.setCurStatus("监测结束");
            }
            // TODO: 2023/5/1 当前计量周期
            List<String> deviceNoList = districtManageMapper.getDeviceNoList(vo.getDistrictId());
            List<Date> dateList = new ArrayList<>();
            deviceNoList.stream().forEach(deviceNo -> {
                Date dateTime = districtManageMapper.getDateTime(deviceNo);
                if (null != dateTime) {
                    dateList.add(dateTime);
                }
            });
            if (CollectionUtils.isNotEmpty(dateList)) {
                Date max = Collections.max(dateList);
                SimpleDateFormat sp = new SimpleDateFormat("MM月-dd日");
                String time = sp.format(max);//获取昨天日期
                vo.setCurMeteringCycle(time + " 0时-24时");
            }
            // TODO: 2023/5/1 累计监测时长
            Integer curMeteringDays = districtManageMapper.getCurMeteringDays(vo.getDistrictId());
            vo.setCurMeteringDays(curMeteringDays);
        });
        return page;
    }

    @Override
    @Transactional
    public R createDistrict(DistrictDto dto) {
        DistrictPo districtPo = new DistrictPo();
//        districtPo.setDistrictName(dto.getDistrictName());
//        districtPo.setCreateId(dto.getCreateId());
//        districtPo.setOrgId(dto.getOrgId());
        BeanUtils.copyProperties(dto,districtPo);
        districtManageMapper.insetDistrict(districtPo);
        List<DistrictTreePo> districtTreePoList = new ArrayList<>();
        DistrictTreePo district = new DistrictTreePo();
        district.setDistrictId(districtPo.getId());
        district.setParentId("-1");
        district.setDeviceNo(districtPo.getDistrictName());
        districtTreePoList.add(district);
        List<DistrictChildDto> list = dto.getChild();
        List<DistrictChildDto> districtChildDtos = tree2list(list);
        districtChildDtos.stream().forEach(districtChildDto -> {
            DistrictTreePo po = new DistrictTreePo();
            po.setDistrictId(districtPo.getId());
            if(StringUtils.isEmpty(districtChildDto.getParentId())){
                throw new RRException("存在设备上级为空的情况，请确认设备信息！");
            }
            po.setParentId(districtChildDto.getParentId());
            if(StringUtils.isEmpty(districtChildDto.getDeviceNo())){
                throw new RRException("存在设备为空的情况，请确认设备信息!");
            }
            int count = districtManageMapper.getCountByDeviceNo(districtChildDto.getDeviceNo());
            if(count > 0){
                throw new RRException("存在编号为"+districtChildDto.getDeviceNo()+"的设备已被其他台区绑定，请重新输入设备编号！");
            }
            po.setDeviceNo(districtChildDto.getDeviceNo());
            po.setDeviceType(districtChildDto.getDeviceType());
            districtTreePoList.add(po);
        });
        districtManageMapper.insertDistrictTree(districtTreePoList);

        return R.ok();
    }

    @Override
    public R updateDistrict(DistrictDto dto) {

        DistrictPo districtPo = new DistrictPo();
//        districtPo.setDistrictName(dto.getDistrictName());
        BeanUtils.copyProperties(dto,districtPo);
        districtPo.setId(dto.getDistrictId());
        districtManageMapper.updateDistrict(districtPo);
        districtManageMapper.deleteDistrictTreeById(dto.getDistrictId());

        List<DistrictTreePo> districtTreePoList = new ArrayList<>();
        DistrictTreePo district = new DistrictTreePo();
        district.setDistrictId(districtPo.getId());
        district.setParentId("-1");
        district.setDeviceNo(districtPo.getDistrictName());
        districtTreePoList.add(district);
        List<DistrictChildDto> list = dto.getChild();
        List<DistrictChildDto> districtChildDtos = tree2list(list);
        districtChildDtos.stream().forEach(districtChildDto -> {
            DistrictTreePo po = new DistrictTreePo();
            po.setDistrictId(districtPo.getId());
            po.setParentId(districtChildDto.getParentId());
            po.setDeviceNo(districtChildDto.getDeviceNo());
            po.setDeviceType(districtChildDto.getDeviceType());
            districtTreePoList.add(po);
        });
        districtManageMapper.insertDistrictTree(districtTreePoList);
        return R.ok();
    }

    public static List<DistrictChildDto> tree2list(List<DistrictChildDto> list) {
        List<DistrictChildDto> result = new ArrayList<>();
        for (DistrictChildDto dto : list) {
            List<DistrictChildDto> c = dto.getChild();
            result.add(dto);
            if (!CollectionUtils.isEmpty(c)) {
                result.addAll(tree2list(c));
                dto.setChild(null);
            }
        }
        return result;
    }

    @Override
    public R getTree(Long districtId) {
        List<DistrictTreeVo> list = districtManageMapper.getDeviceById(districtId);
        DistrictTreeVo districtTreeVo = new DistrictTreeVo();
        if(CollectionUtils.isNotEmpty(list)){
            districtTreeVo = list.get(0);
            addSubCompany(districtTreeVo, list);
        }

        return CommonUtils.msg(districtTreeVo);
    }

    @Override
    public R deleteDistrict(Long districtId) {
        districtManageMapper.deleteDistrictById(districtId);
        int num = districtManageMapper.deleteDistrictTreeById(districtId);
        return CommonUtils.msg(num);
    }

    public static DistrictTreeVo addSubCompany(DistrictTreeVo company, List<DistrictTreeVo> data) {
        //构造一个子公司列表
        List<DistrictTreeVo> subCompany = new ArrayList<>();
        for (DistrictTreeVo item : data) {//遍历数据
            //如果遍历到的部门是当前部门的子部门
            if (item.getParentId().equals(company.getDeviceNo())) {
                //把遍历到的公司添加到子公司列表，并且递归地调用本方法
                DistrictTreeVo districtTreeVo = addSubCompany(item, data);
                subCompany.add(districtTreeVo);
            }
        }
        company.setChild(subCompany);
        return company;
    }

}
